﻿using System;
using System.Collections.Generic;
using Jay.Sc2.Bof.Lib.Action;
using Jay.Sc2.Bof.Lib.Action.Terran;
using Jay.Sc2.Bof.Lib.Tools;

namespace Jay.Sc2.Bof.Lib.State
{
	public class TerranState : State
	{
		public TerranState() : base(TerranRace.Instance) { }
		public class TerranBuilding : StateBuilding
		{
			public TerranBuilding Clone()
			{
				TerranBuilding clone = new TerranBuilding();
				clone.Count = Count;
				clone.Building = Building;
				return clone;
			}
		}
		public class TerranProductionBuilding : TerranBuilding
		{
			public virtual int AvailableForProduction { get { return Count - Production; } }
			public int AvailableForUpgrade { get { return Count - Upgrade; } }
			public override int Available { get { return Math.Min(AvailableForProduction, AvailableForUpgrade); } }
			public void Produced() { Production--; }
			public void Upgraded() { Upgrade--; }
			public int Production;
			public int Upgrade;
			public new TerranProductionBuilding Clone()
			{
				TerranProductionBuilding clone = new TerranProductionBuilding();
				clone.Count = Count;
				clone.Building = Building;
				clone.Production = Production;
				clone.Upgrade = Upgrade;
				return clone;
			}
		}
		public class TerrantProductionBuildingWithReactor : TerranProductionBuilding
		{
			public override int AvailableForProduction { get { return (Count * 2) - Production; } }
			public override int Available { get { return Math.Min(Count - Production / 2, AvailableForUpgrade); } }
			public new TerrantProductionBuildingWithReactor Clone()
			{
				TerrantProductionBuildingWithReactor clone = new TerrantProductionBuildingWithReactor();
				clone.Count = Count;
				clone.Building = Building;
				clone.Production = Production;
				clone.Upgrade = Upgrade;
				return clone;
			}
		}
		public class TerranUpgrade : StateUpgrade
		{
			public TerranUpgrade Clone()
			{
				TerranUpgrade clone = new TerranUpgrade();
				clone.Available = Available;
				clone.Researching = Researching;
				return clone;
			}
		}

		public static TerranState CreateInitialState()
		{
			TerranState state = new TerranState();
			state.TotalBases.Count = state.CommandCenter.Count = 1;
			state.Minerals = 50;
			state.WorkersOnMinerals = state.Food = state.SCV = 6;
			state.Supply = state.CommandCenter.Count * 11;
			return state;
		}

		public TerranProductionBuilding CommandCenter = new TerranProductionBuilding();
		public TerranProductionBuilding OrbitalCommand = new TerranProductionBuilding();
		public TerranProductionBuilding PlanetaryFortress = new TerranProductionBuilding();
		public TerranBuilding SupplyDepot = new TerranBuilding();
		public int ExtraSuppliesCalled = 0;
		public TerranBuilding Refinery = new TerranBuilding();
		public TerranProductionBuilding EngineeringBay = new TerranProductionBuilding();
		public TerranBuilding Bunker = new TerranBuilding();
		public TerranBuilding MissileTurret = new TerranBuilding();
		public TerranBuilding SensorTower = new TerranBuilding();
		public TerranProductionBuilding GhostAcademy = new TerranProductionBuilding();
		public TerranProductionBuilding Armory = new TerranProductionBuilding();
		public TerranProductionBuilding FusionCore = new TerranProductionBuilding();
		public TerranProductionBuilding Barracks = new TerranProductionBuilding();
		public TerranProductionBuilding Factory = new TerranProductionBuilding();
		public TerranProductionBuilding Starport = new TerranProductionBuilding();
		public TerranProductionBuilding BarracksTechLab = new TerranProductionBuilding();
		public TerranProductionBuilding FactoryTechLab = new TerranProductionBuilding();
		public TerranProductionBuilding StarportTechLab = new TerranProductionBuilding();
		public TerrantProductionBuildingWithReactor BarracksReactor = new TerrantProductionBuildingWithReactor();
		public TerrantProductionBuildingWithReactor FactoryReactor = new TerrantProductionBuildingWithReactor();
		public TerrantProductionBuildingWithReactor StarportReactor = new TerrantProductionBuildingWithReactor();

		public List<double> OrbitalCommand_Energy = new List<double>();

		public int SCV;
		public int Marine;
		public int Marauder;
		public int Reaper;
		public int Ghost;
		public int Hellion;
		public int SiegeTank;
		public int Thor;
		public int Viking;
		public int Medivac;
		public int Raven;
		public int Banshee;
		public int Battlecruiser;

		public int Nuke;
		public int Nuke_Producing;
		public int Mules;

		public TerranUpgrade InfantryWeapons1 = new TerranUpgrade();
		public TerranUpgrade InfantryWeapons2 = new TerranUpgrade();
		public TerranUpgrade InfantryWeapons3 = new TerranUpgrade();
		public TerranUpgrade InfantryArmor1 = new TerranUpgrade();
		public TerranUpgrade InfantryArmor2 = new TerranUpgrade();
		public TerranUpgrade InfantryArmor3 = new TerranUpgrade();
		public TerranUpgrade VehicleWeapons1 = new TerranUpgrade();
		public TerranUpgrade VehicleWeapons2 = new TerranUpgrade();
		public TerranUpgrade VehicleWeapons3 = new TerranUpgrade();
		public TerranUpgrade VehiclePlating1 = new TerranUpgrade();
		public TerranUpgrade VehiclePlating2 = new TerranUpgrade();
		public TerranUpgrade VehiclePlating3 = new TerranUpgrade();
		public TerranUpgrade ShipWeapons1 = new TerranUpgrade();
		public TerranUpgrade ShipWeapons2 = new TerranUpgrade();
		public TerranUpgrade ShipWeapons3 = new TerranUpgrade();
		public TerranUpgrade ShipPlating1 = new TerranUpgrade();
		public TerranUpgrade ShipPlating2 = new TerranUpgrade();
		public TerranUpgrade ShipPlating3 = new TerranUpgrade();
		public TerranUpgrade BuildingArmor = new TerranUpgrade();
		public TerranUpgrade HiSecAutoTracking = new TerranUpgrade();
		public TerranUpgrade NeosteelFrames = new TerranUpgrade();
		public TerranUpgrade Stimpack = new TerranUpgrade();
		public TerranUpgrade CombatShield = new TerranUpgrade();
		public TerranUpgrade InfernalPreIgniter = new TerranUpgrade();
		public TerranUpgrade SiegeTech = new TerranUpgrade();
		public TerranUpgrade CorvidReactor = new TerranUpgrade();
		public TerranUpgrade CaduceusReactor = new TerranUpgrade();
		public TerranUpgrade SeekerMissile = new TerranUpgrade();
		public TerranUpgrade DurableMaterials = new TerranUpgrade();
		public TerranUpgrade CloakingField = new TerranUpgrade();
		public TerranUpgrade NitroPacks = new TerranUpgrade();
		public TerranUpgrade ConcussiveShells = new TerranUpgrade();
		public TerranUpgrade StrikeCannon = new TerranUpgrade();
		public TerranUpgrade MoebiusReactor = new TerranUpgrade();
		public TerranUpgrade PersonalCloaking = new TerranUpgrade();
		public TerranUpgrade BehemothReactor = new TerranUpgrade();
		public TerranUpgrade WeaponRefit = new TerranUpgrade();

		public TerranBuilding TotalBases = new TerranBuilding();
		public override IBuilding Bases { get { return TotalBases; } }
		public override IBuilding GasBuilding { get { return Refinery; } }
		public override int Workers { get { return SCV; } set { SCV = value; } }
		public override int Army
		{
			get
			{
				return this.Banshee * 3 +
					this.Battlecruiser * 6 +
					this.Ghost * 2 +
					this.Hellion * 2 +
					this.Marauder * 2 +
					this.Marine +
					this.Medivac * 2 +
					this.Raven * 2 +
					this.Reaper +
					this.SiegeTank * 3 +
					this.Thor * 6 +
					this.Viking * 2;
			}
		}
		public override int MineralsIncome { get { return IncomeUtil.GetMineralsIncome(WorkersOnMinerals, Mules, MineralPatches); } }
		public override double Score(IState state)
		{
			TerranState s = state as TerranState;
			double score = 0.0;
			score += Score(this.Armory, s.Armory, 250.0);
			score += Score(this.Banshee, s.Banshee, 250.0);
			score += Score(this.Barracks, s.Barracks, 150.0);
			score += Score(this.BarracksReactor.Count, s.BarracksReactor.Count, 250.0);
			score += Score(this.BarracksTechLab.Count, s.BarracksTechLab.Count, 225.0);
			score += Score(this.Battlecruiser, s.Battlecruiser, 700.0);
			score += Score(this.BehemothReactor, s.BehemothReactor, 300.0);
			score += Score(this.BuildingArmor, s.BuildingArmor, 300.0);
			score += Score(this.Bunker, s.Bunker, 100.0);
			score += Score(this.CaduceusReactor, s.CaduceusReactor, 200.0);
			score += Score(this.CloakingField, s.CloakingField, 400.0);
			score += Score(this.CombatShield, s.CombatShield, 200.0);
			score += Score(this.CommandCenter, s.CommandCenter, 400.0);
			score += Score(this.ConcussiveShells, s.ConcussiveShells, 100.0);
			score += Score(this.CorvidReactor, s.CorvidReactor, 300.0);
			score += Score(this.DurableMaterials, s.DurableMaterials, 300.0);
			score += Score(this.EngineeringBay, s.EngineeringBay, 125.0);
			score += Score(this.Factory, s.Factory, 250.0);
			score += Score(this.FactoryReactor, s.FactoryReactor, 350.0);
			score += Score(this.FactoryTechLab, s.FactoryTechLab, 325.0);
			score += Score(this.FusionCore, s.FusionCore, 300.0);
			score += Score(this.Ghost, s.Ghost, 300.0);
			score += Score(this.GhostAcademy, s.GhostAcademy, 200.0);
			score += Score(this.Hellion, s.Hellion, 100.0);
			score += Score(this.HiSecAutoTracking, s.HiSecAutoTracking, 200.0);
			score += Score(this.InfantryArmor1, s.InfantryArmor1, 200.0);
			score += Score(this.InfantryArmor2, s.InfantryArmor2, 350.0);
			score += Score(this.InfantryArmor3, s.InfantryArmor3, 500.0);
			score += Score(this.InfantryWeapons1, s.InfantryWeapons1, 200.0);
			score += Score(this.InfantryWeapons2, s.InfantryWeapons2, 350.0);
			score += Score(this.InfantryWeapons3, s.InfantryWeapons3, 500.0);
			score += Score(this.InfernalPreIgniter, s.InfernalPreIgniter, 300.0);
			score += Score(this.Marauder, s.Marauder, 125.0);
			score += Score(this.Marine, s.Marine, 50.0);
			score += Score(this.Medivac, s.Medivac, 200.0);
			score += Score(this.MissileTurret, s.MissileTurret, 100.0);
			score += Score(this.MoebiusReactor, s.MoebiusReactor, 200.0);
			score += Score(this.NeosteelFrames, s.NeosteelFrames, 200.0);
			score += Score(this.NitroPacks, s.NitroPacks, 100.0);
			score += Score(this.Nuke, s.Nuke, 200.0);
			score += Score(this.OrbitalCommand, s.OrbitalCommand, 150.0);
			score += Score(this.PersonalCloaking, s.PersonalCloaking, 300.0);
			score += Score(this.PlanetaryFortress, s.PlanetaryFortress, 300.0);
			score += Score(this.Raven, s.Raven, 300.0);
			score += Score(this.Reaper, s.Reaper, 100.0);
			score += Score(this.Refinery, s.Refinery, 75.0);
			score += Score(this.SCV, s.SCV, 50.0);
			score += Score(this.SeekerMissile, s.SeekerMissile, 300.0);
			score += Score(this.SensorTower, s.SensorTower, 225.0);
			score += Score(this.ShipPlating1, s.ShipPlating1, 300.0);
			score += Score(this.ShipPlating2, s.ShipPlating3, 450.0);
			score += Score(this.ShipPlating3, s.ShipPlating3, 600.0);
			score += Score(this.ShipWeapons1, s.ShipWeapons1, 200.0);
			score += Score(this.ShipWeapons2, s.ShipWeapons2, 350.0);
			score += Score(this.ShipWeapons3, s.ShipWeapons3, 500.0);
			score += Score(this.SiegeTank, s.SiegeTank, 275.0);
			score += Score(this.SiegeTech, s.SiegeTech, 200.0);
			score += Score(this.Starport, s.Starport, 250.0);
			score += Score(this.StarportReactor, s.StarportReactor, 350.0);
			score += Score(this.StarportTechLab, s.StarportTechLab, 325.0);
			score += Score(this.Stimpack, s.Stimpack, 200.0);
			score += Score(this.StrikeCannon, s.StrikeCannon, 300.0);
			score += Score(this.SupplyDepot, s.SupplyDepot, 100.0);
			score += Score(this.Thor, s.Thor, 500.0);
			score += Score(this.VehiclePlating1, s.VehiclePlating1, 200.0);
			score += Score(this.VehiclePlating2, s.VehiclePlating2, 350.0);
			score += Score(this.VehiclePlating3, s.VehiclePlating3, 500.0);
			score += Score(this.VehicleWeapons1, s.VehicleWeapons1, 200.0);
			score += Score(this.VehicleWeapons2, s.VehicleWeapons2, 350.0);
			score += Score(this.VehicleWeapons3, s.VehicleWeapons3, 500.0);
			score += Score(this.Viking, s.Viking, 225.0);
			score += Score(this.WeaponRefit, s.WeaponRefit, 300.0);
			score += Score((int)this.Minerals, (int)s.Minerals, 1.0);
			score += Score((int)this.Gas, (int)s.Gas, 1.0);
			return score;
		}
		public override void IncrementTime()
		{
			base.IncrementTime();
			for (int c = 0; c < OrbitalCommand_Energy.Count; c++)
				if (OrbitalCommand_Energy[c] < 200)
					OrbitalCommand_Energy[c] = Math.Min(OrbitalCommand_Energy[c] + 0.56, 200);
		}

		public override bool IsSatisfying(IState goal)
		{
			TerranState s = goal as TerranState;
			if (this.Armory.Count < s.Armory.Count) return false;
			if (this.Banshee < s.Banshee) return false;
			if (this.Barracks.Count < s.Barracks.Count) return false;
			if (this.BarracksReactor.Count < s.BarracksReactor.Count) return false;
			if (this.BarracksTechLab.Count < s.BarracksTechLab.Count) return false;
			if (this.Battlecruiser < s.Battlecruiser) return false;
			if (!this.BehemothReactor.Available && s.BehemothReactor.Available) return false;
			if (!this.BuildingArmor.Available && s.BuildingArmor.Available) return false;
			if (this.Bunker.Count < s.Bunker.Count) return false;
			if (!this.CaduceusReactor.Available && s.CaduceusReactor.Available) return false;
			if (!this.CloakingField.Available && s.CloakingField.Available) return false;
			if (!this.CombatShield.Available && s.CombatShield.Available) return false;
			if (this.CommandCenter.Count < s.CommandCenter.Count) return false;
			if (!this.ConcussiveShells.Available && s.ConcussiveShells.Available) return false;
			if (!this.CorvidReactor.Available && s.CorvidReactor.Available) return false;
			if (!this.DurableMaterials.Available && s.DurableMaterials.Available) return false;
			if (this.EngineeringBay.Count < s.EngineeringBay.Count) return false;
			if (this.Factory.Count < s.Factory.Count) return false;
			if (this.FactoryReactor.Count < s.FactoryReactor.Count) return false;
			if (this.FactoryTechLab.Count < s.FactoryTechLab.Count) return false;
			if (this.FusionCore.Count < s.FusionCore.Count) return false;
			if (this.Ghost < s.Ghost) return false;
			if (this.GhostAcademy.Count < s.GhostAcademy.Count) return false;
			if (this.Hellion < s.Hellion) return false;
			if (!this.HiSecAutoTracking.Available && s.HiSecAutoTracking.Available) return false;
			if (!this.InfantryArmor1.Available && s.InfantryArmor1.Available) return false;
			if (!this.InfantryArmor2.Available && s.InfantryArmor2.Available) return false;
			if (!this.InfantryArmor3.Available && s.InfantryArmor3.Available) return false;
			if (!this.InfantryWeapons1.Available && s.InfantryWeapons1.Available) return false;
			if (!this.InfantryWeapons2.Available && s.InfantryWeapons2.Available) return false;
			if (!this.InfantryWeapons3.Available && s.InfantryWeapons3.Available) return false;
			if (!this.InfernalPreIgniter.Available && s.InfernalPreIgniter.Available) return false;
			if (this.Marauder < s.Marauder) return false;
			if (this.Marine < s.Marine) return false;
			if (this.Medivac < s.Medivac) return false;
			if (this.MissileTurret.Count < s.MissileTurret.Count) return false;
			if (!this.MoebiusReactor.Available && s.MoebiusReactor.Available) return false;
			if (!this.NeosteelFrames.Available && s.NeosteelFrames.Available) return false;
			if (!this.NitroPacks.Available && s.NitroPacks.Available) return false;
			if (this.Nuke < s.Nuke) return false;
			if (this.OrbitalCommand.Count < s.OrbitalCommand.Count) return false;
			if (!this.PersonalCloaking.Available && s.PersonalCloaking.Available) return false;
			if (this.PlanetaryFortress.Count < s.PlanetaryFortress.Count) return false;
			if (this.Raven < s.Raven) return false;
			if (this.Reaper < s.Reaper) return false;
			if (this.Refinery.Count < s.Refinery.Count) return false;
			if (this.SCV < s.SCV) return false;
			if (!this.SeekerMissile.Available && s.SeekerMissile.Available) return false;
			if (this.SensorTower.Count < s.SensorTower.Count) return false;
			if (!this.ShipPlating1.Available && s.ShipPlating1.Available) return false;
			if (!this.ShipPlating2.Available && s.ShipPlating3.Available) return false;
			if (!this.ShipPlating3.Available && s.ShipPlating3.Available) return false;
			if (!this.ShipWeapons1.Available && s.ShipWeapons1.Available) return false;
			if (!this.ShipWeapons2.Available && s.ShipWeapons2.Available) return false;
			if (!this.ShipWeapons3.Available && s.ShipWeapons3.Available) return false;
			if (this.SiegeTank < s.SiegeTank) return false;
			if (!this.SiegeTech.Available && s.SiegeTech.Available) return false;
			if (this.Starport.Count < s.Starport.Count) return false;
			if (this.StarportReactor.Count < s.StarportReactor.Count) return false;
			if (this.StarportTechLab.Count < s.StarportTechLab.Count) return false;
			if (!this.Stimpack.Available && s.Stimpack.Available) return false;
			if (!this.StrikeCannon.Available && s.StrikeCannon.Available) return false;
			if (this.SupplyDepot.Count < s.SupplyDepot.Count) return false;
			if (this.Thor < s.Thor) return false;
			if (!this.VehiclePlating1.Available && s.VehiclePlating1.Available) return false;
			if (!this.VehiclePlating2.Available && s.VehiclePlating2.Available) return false;
			if (!this.VehiclePlating3.Available && s.VehiclePlating3.Available) return false;
			if (!this.VehicleWeapons1.Available && s.VehicleWeapons1.Available) return false;
			if (!this.VehicleWeapons2.Available && s.VehicleWeapons2.Available) return false;
			if (!this.VehicleWeapons3.Available && s.VehicleWeapons3.Available) return false;
			if (this.Viking < s.Viking) return false;
			if (!this.WeaponRefit.Available && s.WeaponRefit.Available) return false;
			return true;
		}

		public override IState Clone()
		{
			TerranState s = new TerranState();
			s.OrbitalCommand_Energy = new List<double>(OrbitalCommand_Energy);
			s.Armory = this.Armory.Clone();
			s.Banshee = this.Banshee;
			s.Barracks = this.Barracks.Clone();
			s.BarracksReactor = this.BarracksReactor.Clone();
			s.BarracksTechLab = this.BarracksTechLab.Clone();
			s.Battlecruiser = this.Battlecruiser;
			s.BehemothReactor = this.BehemothReactor.Clone();
			s.BuildingArmor = this.BuildingArmor.Clone();
			s.Bunker = this.Bunker.Clone();
			s.CaduceusReactor = this.CaduceusReactor.Clone();
			s.CloakingField = this.CloakingField.Clone();
			s.CombatShield = this.CombatShield.Clone();
			s.CommandCenter = this.CommandCenter.Clone();
			s.ConcussiveShells = this.ConcussiveShells.Clone();
			s.CorvidReactor = this.CorvidReactor.Clone();
			s.DurableMaterials = this.DurableMaterials.Clone();
			s.EngineeringBay = this.EngineeringBay.Clone();
			s.Factory = this.Factory.Clone();
			s.FactoryReactor = this.FactoryReactor.Clone();
			s.FactoryTechLab = this.FactoryTechLab.Clone();
			s.FusionCore = this.FusionCore.Clone();
			s.Ghost = this.Ghost;
			s.GhostAcademy = this.GhostAcademy.Clone();
			s.Hellion = this.Hellion;
			s.HiSecAutoTracking = this.HiSecAutoTracking.Clone();
			s.InfantryArmor1 = this.InfantryArmor1.Clone();
			s.InfantryArmor2 = this.InfantryArmor2.Clone();
			s.InfantryArmor3 = this.InfantryArmor3.Clone();
			s.InfantryWeapons1 = this.InfantryWeapons1.Clone();
			s.InfantryWeapons2 = this.InfantryWeapons2.Clone();
			s.InfantryWeapons3 = this.InfantryWeapons3.Clone();
			s.InfernalPreIgniter = this.InfernalPreIgniter.Clone();
			s.Marauder = this.Marauder;
			s.Marine = this.Marine;
			s.Medivac = this.Medivac;
			s.MissileTurret = this.MissileTurret.Clone();
			s.MoebiusReactor = this.MoebiusReactor.Clone();
			s.Mules = this.Mules;
			s.NeosteelFrames = this.NeosteelFrames.Clone();
			s.NitroPacks = this.NitroPacks.Clone();
			s.Nuke = this.Nuke;
			s.OrbitalCommand = this.OrbitalCommand.Clone();
			s.PersonalCloaking = this.PersonalCloaking.Clone();
			s.PlanetaryFortress = this.PlanetaryFortress.Clone();
			s.Raven = this.Raven;
			s.Reaper = this.Reaper;
			s.Refinery = this.Refinery.Clone();
			s.SCV = this.SCV;
			s.SeekerMissile = this.SeekerMissile.Clone();
			s.SensorTower = this.SensorTower.Clone();
			s.ShipPlating1 = this.ShipPlating1.Clone();
			s.ShipPlating2 = this.ShipPlating2.Clone();
			s.ShipPlating3 = this.ShipPlating3.Clone();
			s.ShipWeapons1 = this.ShipWeapons1.Clone();
			s.ShipWeapons2 = this.ShipWeapons2.Clone();
			s.ShipWeapons3 = this.ShipWeapons3.Clone();
			s.SiegeTank = this.SiegeTank;
			s.SiegeTech = this.SiegeTech.Clone();
			s.Starport = this.Starport.Clone();
			s.StarportReactor = this.StarportReactor.Clone();
			s.StarportTechLab = this.StarportTechLab.Clone();
			s.Stimpack = this.Stimpack.Clone();
			s.StrikeCannon = this.StrikeCannon.Clone();
			s.SupplyDepot = this.SupplyDepot.Clone();
			s.Thor = this.Thor;
			s.VehiclePlating1 = this.VehiclePlating1.Clone();
			s.VehiclePlating2 = this.VehiclePlating2.Clone();
			s.VehiclePlating3 = this.VehiclePlating3.Clone();
			s.VehicleWeapons1 = this.VehicleWeapons1.Clone();
			s.VehicleWeapons2 = this.VehicleWeapons2.Clone();
			s.VehicleWeapons3 = this.VehicleWeapons3.Clone();
			s.Viking = this.Viking;
			s.WeaponRefit = this.WeaponRefit.Clone();
			s.Minerals = this.Minerals;
			s.WorkersOnGas = this.WorkersOnGas;
			s.WorkersOnMinerals = this.WorkersOnMinerals;
			s.Supply = this.Supply;
			s.m_SupplyBuilding = this.SupplyBuilding;
			s.Food = this.Food;
			s.Time = this.Time;
			s.TotalBases = this.TotalBases.Clone();
			return s;
		}

		private int m_OrbitalCommandProducingMule;
		public static void ProduceMule(IBuildOrder bo, int delay)
		{
			TerranState state = bo.State as TerranState;
			bo.AddAction(state.Time + delay, new ActionGeneric("ActionCallMule", (ActionGeneric.ActionExecuteDelegate)delegate(IBuildOrder ibo)
			{
				TerranState istate = ibo.State as TerranState;
				if (istate.m_OrbitalCommandProducingMule < istate.OrbitalCommand.Count)
				{
					if (istate.RemoveEnergyFromOrbitalCommand(50))
					{
						istate.m_OrbitalCommandProducingMule++;
						istate.Mules++;
						ibo.AddAction(istate.Time + 90, new ActionGeneric("ActionFailedMule", null));
						ibo.AddAction(istate.Time + 90, new ActionGeneric("ActionCallMule", SpawnMule));
					}
				}
			}));
		}
		private bool RemoveEnergyFromOrbitalCommand(int energy)
		{
			for (int c = 0; c < OrbitalCommand_Energy.Count; c++)
				if (OrbitalCommand_Energy[c] >= energy)
				{
					OrbitalCommand_Energy[c] -= energy;
					return true;
				}
			return false;
		}
		private static void SpawnMule(IBuildOrder ibo)
		{
			TerranState istate = ibo.State as TerranState;
			if (istate.RemoveEnergyFromOrbitalCommand(50))
			{
				ibo.AddAction(istate.Time + 90, new ActionGeneric("ActionFailedMule", null));
				ibo.AddAction(istate.Time + 90, new ActionGeneric("ActionCallMule", SpawnMule));
			}
			else
			{
				istate.m_OrbitalCommandProducingMule--;
				istate.Mules--;
			}
		}

		public override IList<IAction> NeededActions
		{
			get
			{
				List<IAction> al = new List<IAction>();
				AddNeededAction(al, SCV - 6, ActionProduceSCV.Instance);
				AddNeededAction(al, Armory, ActionProduceArmory.Instance);
				AddNeededAction(al, Banshee, ActionProduceBanshee.Instance);
				AddNeededAction(al, Barracks.Count + BarracksReactor.Count + BarracksTechLab.Count, ActionProduceBarracks.Instance);
				AddNeededAction(al, BarracksReactor, ActionProduceReactorOnBarracks.Instance);
				AddNeededAction(al, BarracksTechLab, ActionProduceTechLabOnBarracks.Instance);
				AddNeededAction(al, Battlecruiser, ActionProduceBattlecruiser.Instance);
				AddNeededAction(al, BehemothReactor, ActionUpgradeBehemothReactor.Instance);
				AddNeededAction(al, BuildingArmor, ActionUpgradeBuildingArmor.Instance);
				AddNeededAction(al, Bunker, ActionProduceBunker.Instance);
				AddNeededAction(al, CaduceusReactor, ActionUpgradeCaduceusReactor.Instance);
				AddNeededAction(al, CloakingField, ActionUpgradeCloakingField.Instance);
				AddNeededAction(al, CombatShield, ActionUpgradeCombatShield.Instance);
				AddNeededAction(al, CommandCenter.Count + OrbitalCommand.Count + PlanetaryFortress.Count - 1, ActionProduceCommandCenter.Instance);
				AddNeededAction(al, ConcussiveShells, ActionUpgradeConcussiveShells.Instance);
				AddNeededAction(al, CorvidReactor, ActionUpgradeCorvidReactor.Instance);
				AddNeededAction(al, DurableMaterials, ActionUpgradeDurableMaterials.Instance);
				AddNeededAction(al, EngineeringBay, ActionProduceEngineeringBay.Instance);
				AddNeededAction(al, Factory.Count + FactoryReactor.Count + FactoryTechLab.Count, ActionProduceFactory.Instance);
				AddNeededAction(al, FactoryReactor, ActionProduceReactorOnFactory.Instance);
				AddNeededAction(al, FactoryTechLab, ActionProduceTechLabOnFactory.Instance);
				AddNeededAction(al, FusionCore, ActionProduceFusionCore.Instance);
				AddNeededAction(al, Ghost, ActionProduceGhost.Instance);
				AddNeededAction(al, Math.Max(GhostAcademy.Count, Nuke), ActionProduceGhostAcademy.Instance);
				AddNeededAction(al, Hellion, ActionProduceHellion.Instance);
				AddNeededAction(al, HiSecAutoTracking, ActionUpgradeHiSecAutoTracking.Instance);
				AddNeededAction(al, InfantryArmor1, ActionUpgradeInfantryArmor1.Instance);
				AddNeededAction(al, InfantryArmor2, ActionUpgradeInfantryArmor2.Instance);
				AddNeededAction(al, InfantryArmor3, ActionUpgradeInfantryArmor3.Instance);
				AddNeededAction(al, InfantryWeapons1, ActionUpgradeInfantryWeapons1.Instance);
				AddNeededAction(al, InfantryWeapons2, ActionUpgradeInfantryWeapons2.Instance);
				AddNeededAction(al, InfantryWeapons3, ActionUpgradeInfantryWeapons3.Instance);
				AddNeededAction(al, InfernalPreIgniter, ActionUpgradeInfernalPreIgniter.Instance);
				AddNeededAction(al, Marauder, ActionProduceMarauder.Instance);
				AddNeededAction(al, Marine, ActionProduceMarine.Instance);
				AddNeededAction(al, Medivac, ActionProduceMedivac.Instance);
				AddNeededAction(al, MissileTurret, ActionProduceMissileTurret.Instance);
				AddNeededAction(al, MoebiusReactor, ActionUpgradeMoebiusReactor.Instance);
				AddNeededAction(al, NeosteelFrames, ActionUpgradeNeosteelFrames.Instance);
				AddNeededAction(al, NitroPacks, ActionUpgradeNitroPacks.Instance);
				AddNeededAction(al, Nuke, ActionProduceNuke.Instance);
				AddNeededAction(al, OrbitalCommand, ActionProduceOrbitalCommand.Instance);
				AddNeededAction(al, PersonalCloaking, ActionUpgradePersonalCloaking.Instance);
				AddNeededAction(al, PlanetaryFortress, ActionProducePlanetaryFortress.Instance);
				AddNeededAction(al, Raven, ActionProduceRaven.Instance);
				AddNeededAction(al, Reaper, ActionProduceReaper.Instance);
				AddNeededAction(al, Refinery, ActionProduceRefinery.Instance);
				AddNeededAction(al, SeekerMissile, ActionUpgradeSeekerMissile.Instance);
				AddNeededAction(al, SensorTower, ActionProduceSensorTower.Instance);
				AddNeededAction(al, ShipPlating1, ActionUpgradeShipPlating1.Instance);
				AddNeededAction(al, ShipPlating2, ActionUpgradeShipPlating2.Instance);
				AddNeededAction(al, ShipPlating3, ActionUpgradeShipPlating3.Instance);
				AddNeededAction(al, ShipWeapons1, ActionUpgradeShipWeapons1.Instance);
				AddNeededAction(al, ShipWeapons2, ActionUpgradeShipWeapons2.Instance);
				AddNeededAction(al, ShipWeapons3, ActionUpgradeShipWeapons3.Instance);
				AddNeededAction(al, SiegeTank, ActionProduceSiegeTank.Instance);
				AddNeededAction(al, SiegeTech, ActionUpgradeSiegeTech.Instance);
				AddNeededAction(al, Starport.Count + StarportReactor.Count + StarportTechLab.Count, ActionProduceStarport.Instance);
				AddNeededAction(al, StarportReactor, ActionProduceReactorOnStarport.Instance);
				AddNeededAction(al, StarportTechLab, ActionProduceTechLabOnStarport.Instance);
				AddNeededAction(al, Stimpack, ActionUpgradeStimpack.Instance);
				AddNeededAction(al, StrikeCannon, ActionUpgradeStrikeCannon.Instance);
				AddNeededAction(al, SupplyDepot, ActionProduceSupplyDepot.Instance);
				AddNeededAction(al, Thor, ActionProduceThor.Instance);
				AddNeededAction(al, VehiclePlating1, ActionUpgradeVehiclePlating1.Instance);
				AddNeededAction(al, VehiclePlating2, ActionUpgradeVehiclePlating2.Instance);
				AddNeededAction(al, VehiclePlating3, ActionUpgradeVehiclePlating3.Instance);
				AddNeededAction(al, VehicleWeapons1, ActionUpgradeVehicleWeapons1.Instance);
				AddNeededAction(al, VehicleWeapons2, ActionUpgradeVehicleWeapons2.Instance);
				AddNeededAction(al, VehicleWeapons3, ActionUpgradeVehicleWeapons3.Instance);
				AddNeededAction(al, Viking, ActionProduceViking.Instance);
				AddNeededAction(al, WeaponRefit, ActionUpgradeWeaponRefit.Instance);
				return al;
			}
		}

		public override IActionList BasicBuildOrder
		{
			get 
			{
				ActionList al = new ActionList(TerranRace.Instance);
				AddNeededActionWithRequirements(al, SCV - 6, ActionProduceSCV.Instance);
				AddNeededActionWithRequirements(al, Armory, ActionProduceArmory.Instance);
				AddNeededActionWithRequirements(al, Banshee, ActionProduceBanshee.Instance);
				AddNeededActionWithRequirements(al, Barracks.Count + BarracksReactor.Count + BarracksTechLab.Count, ActionProduceBarracks.Instance);
				AddNeededActionWithRequirements(al, BarracksReactor, ActionProduceReactorOnBarracks.Instance);
				AddNeededActionWithRequirements(al, BarracksTechLab, ActionProduceTechLabOnBarracks.Instance);
				AddNeededActionWithRequirements(al, Battlecruiser, ActionProduceBattlecruiser.Instance);
				AddNeededActionWithRequirements(al, BehemothReactor, ActionUpgradeBehemothReactor.Instance);
				AddNeededActionWithRequirements(al, BuildingArmor, ActionUpgradeBuildingArmor.Instance);
				AddNeededActionWithRequirements(al, Bunker, ActionProduceBunker.Instance);
				AddNeededActionWithRequirements(al, CaduceusReactor, ActionUpgradeCaduceusReactor.Instance);
				AddNeededActionWithRequirements(al, CloakingField, ActionUpgradeCloakingField.Instance);
				AddNeededActionWithRequirements(al, CombatShield, ActionUpgradeCombatShield.Instance);
				AddNeededActionWithRequirements(al, CommandCenter.Count + OrbitalCommand.Count + PlanetaryFortress.Count - 1, ActionProduceCommandCenter.Instance);
				AddNeededActionWithRequirements(al, ConcussiveShells, ActionUpgradeConcussiveShells.Instance);
				AddNeededActionWithRequirements(al, CorvidReactor, ActionUpgradeCorvidReactor.Instance);
				AddNeededActionWithRequirements(al, DurableMaterials, ActionUpgradeDurableMaterials.Instance);
				AddNeededActionWithRequirements(al, EngineeringBay, ActionProduceEngineeringBay.Instance);
				AddNeededActionWithRequirements(al, Factory.Count + FactoryReactor.Count + FactoryTechLab.Count, ActionProduceFactory.Instance);
				AddNeededActionWithRequirements(al, FactoryReactor, ActionProduceReactorOnFactory.Instance);
				AddNeededActionWithRequirements(al, FactoryTechLab, ActionProduceTechLabOnFactory.Instance);
				AddNeededActionWithRequirements(al, FusionCore, ActionProduceFusionCore.Instance);
				AddNeededActionWithRequirements(al, Ghost, ActionProduceGhost.Instance);
				AddNeededActionWithRequirements(al, Math.Max(GhostAcademy.Count, Nuke), ActionProduceGhostAcademy.Instance);
				AddNeededActionWithRequirements(al, Hellion, ActionProduceHellion.Instance);
				AddNeededActionWithRequirements(al, HiSecAutoTracking, ActionUpgradeHiSecAutoTracking.Instance);
				AddNeededActionWithRequirements(al, InfantryArmor1, ActionUpgradeInfantryArmor1.Instance);
				AddNeededActionWithRequirements(al, InfantryArmor2, ActionUpgradeInfantryArmor2.Instance);
				AddNeededActionWithRequirements(al, InfantryArmor3, ActionUpgradeInfantryArmor3.Instance);
				AddNeededActionWithRequirements(al, InfantryWeapons1, ActionUpgradeInfantryWeapons1.Instance);
				AddNeededActionWithRequirements(al, InfantryWeapons2, ActionUpgradeInfantryWeapons2.Instance);
				AddNeededActionWithRequirements(al, InfantryWeapons3, ActionUpgradeInfantryWeapons3.Instance);
				AddNeededActionWithRequirements(al, InfernalPreIgniter, ActionUpgradeInfernalPreIgniter.Instance);
				AddNeededActionWithRequirements(al, Marauder, ActionProduceMarauder.Instance);
				AddNeededActionWithRequirements(al, Marine, ActionProduceMarine.Instance);
				AddNeededActionWithRequirements(al, Medivac, ActionProduceMedivac.Instance);
				AddNeededActionWithRequirements(al, MissileTurret, ActionProduceMissileTurret.Instance);
				AddNeededActionWithRequirements(al, MoebiusReactor, ActionUpgradeMoebiusReactor.Instance);
				AddNeededActionWithRequirements(al, NeosteelFrames, ActionUpgradeNeosteelFrames.Instance);
				AddNeededActionWithRequirements(al, NitroPacks, ActionUpgradeNitroPacks.Instance);
				AddNeededActionWithRequirements(al, Nuke, ActionProduceNuke.Instance);
				AddNeededActionWithRequirements(al, OrbitalCommand, ActionProduceOrbitalCommand.Instance);
				AddNeededActionWithRequirements(al, PersonalCloaking, ActionUpgradePersonalCloaking.Instance);
				AddNeededActionWithRequirements(al, PlanetaryFortress, ActionProducePlanetaryFortress.Instance);
				AddNeededActionWithRequirements(al, Raven, ActionProduceRaven.Instance);
				AddNeededActionWithRequirements(al, Reaper, ActionProduceReaper.Instance);
				AddNeededActionWithRequirements(al, Refinery, ActionProduceRefinery.Instance);
				AddNeededActionWithRequirements(al, SeekerMissile, ActionUpgradeSeekerMissile.Instance);
				AddNeededActionWithRequirements(al, SensorTower, ActionProduceSensorTower.Instance);
				AddNeededActionWithRequirements(al, ShipPlating1, ActionUpgradeShipPlating1.Instance);
				AddNeededActionWithRequirements(al, ShipPlating2, ActionUpgradeShipPlating2.Instance);
				AddNeededActionWithRequirements(al, ShipPlating3, ActionUpgradeShipPlating3.Instance);
				AddNeededActionWithRequirements(al, ShipWeapons1, ActionUpgradeShipWeapons1.Instance);
				AddNeededActionWithRequirements(al, ShipWeapons2, ActionUpgradeShipWeapons2.Instance);
				AddNeededActionWithRequirements(al, ShipWeapons3, ActionUpgradeShipWeapons3.Instance);
				AddNeededActionWithRequirements(al, SiegeTank, ActionProduceSiegeTank.Instance);
				AddNeededActionWithRequirements(al, SiegeTech, ActionUpgradeSiegeTech.Instance);
				AddNeededActionWithRequirements(al, Starport.Count + StarportReactor.Count + StarportTechLab.Count, ActionProduceStarport.Instance);
				AddNeededActionWithRequirements(al, StarportReactor, ActionProduceReactorOnStarport.Instance);
				AddNeededActionWithRequirements(al, StarportTechLab, ActionProduceTechLabOnStarport.Instance);
				AddNeededActionWithRequirements(al, Stimpack, ActionUpgradeStimpack.Instance);
				AddNeededActionWithRequirements(al, StrikeCannon, ActionUpgradeStrikeCannon.Instance);
				AddNeededActionWithRequirements(al, SupplyDepot, ActionProduceSupplyDepot.Instance);
				AddNeededActionWithRequirements(al, Thor, ActionProduceThor.Instance);
				AddNeededActionWithRequirements(al, VehiclePlating1, ActionUpgradeVehiclePlating1.Instance);
				AddNeededActionWithRequirements(al, VehiclePlating2, ActionUpgradeVehiclePlating2.Instance);
				AddNeededActionWithRequirements(al, VehiclePlating3, ActionUpgradeVehiclePlating3.Instance);
				AddNeededActionWithRequirements(al, VehicleWeapons1, ActionUpgradeVehicleWeapons1.Instance);
				AddNeededActionWithRequirements(al, VehicleWeapons2, ActionUpgradeVehicleWeapons2.Instance);
				AddNeededActionWithRequirements(al, VehicleWeapons3, ActionUpgradeVehicleWeapons3.Instance);
				AddNeededActionWithRequirements(al, Viking, ActionProduceViking.Instance);
				AddNeededActionWithRequirements(al, WeaponRefit, ActionUpgradeWeaponRefit.Instance);
				return al;
			}
		}
	}
}
